package io.noties.markwon.base.order

import timber.log.Timber

//https://blog.csdn.net/u013072976/article/details/51698196?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-51698196-blog-117485803.235^v28^pc_relevant_recovery_v2&spm=1001.2101.3001.4242.1&utm_relevant_index=2


fun interface IOrderIndex {
    fun  getIndexString( index:Int):String
}



class NumberIndex : IOrderIndex {
    override fun getIndexString(index: Int): String {
        return index.toString() + ""
    }
}

class EnglishLetterIndex : IOrderIndex {
    var array = arrayOf(
        "a",
        "b",
        "c",
        "d",
        "e",
        "f",
        "g",
        "h",
        "i",
        "j",
        "k",
        "l",
        "m",
        "n",
        "o",
        "p",
        "q",
        "r",
        "s",
        "t",
        "u",
        "v",
        "w",
        "x",
        "y",
        "z"
    )

    override fun getIndexString(index: Int): String {
        var result = ""
        result = switchNumToLetter(index)
        return result
    }

    fun switchNumToLetter(index: Int): String {
        if (index <= 0) {
            return ""
        }
        var out = ""
        val count = 26
        if (index in 1..count) {
            out = array[index - 1]
            return out
        } else {
            out = if (index % count == 0) {
                switchNumToLetter(index / count - 1) + array[count - 1]
            } else {
                switchNumToLetter(index / count) + switchNumToLetter(index - index / count * count)
            }
        }
        return out
    }
}

class RomanNumberIndex : IOrderIndex {
    override fun getIndexString(index: Int): String {
        var result = ""
        result = intToRoman(index)
        return result
    }

    /**
     * @param s
     * - String Roman
     * @return int number
     */
    fun romanToInt(s: String): Int {
        if (s.isEmpty()) return 0
        var result = 0
        var current = 0
        var pre = singleRomanToInt(s[0])
        var temp = pre
        for (i in 1 until s.length) {
            current = singleRomanToInt(s[i])
            if (current == pre) temp += current else if (current > pre) {
                temp = current - temp
            } else if (current < pre) {
                result += temp
                temp = current
            }
            pre = current
        }
        result += temp
        return result
    }

    /**
     * @param c
     * single Roman
     * @return single number
     */
    fun singleRomanToInt(c: Char): Int {
        return when (c) {
            'I' -> 1
            'V' -> 5
            'X' -> 10
            'L' -> 50
            'C' -> 100
            'D' -> 500
            'M' -> 1000
            else -> 0
        }
    }

    /**
     * @param n
     * - input single int
     * @param nth
     * must start from 1; 1 <= nth <= 4
     * @return String single Roman
     */
    fun singleDigitToRoman(n: Int, nth: Int): String {
        var nth = nth
        if (n == 0) {
            return ""
        }
        nth = 2 * nth - 1 // nth must start from 1
        val singleRoman = charArrayOf('I', 'V', 'X', 'L', 'C', 'D', 'M', 'Z', 'E') // never
        // use
        // 'Z'
        // &
        // 'E'
        val rsb = StringBuilder("")
        if (n <= 3) {
            for (i in 0 until n) {
                rsb.append(singleRoman[nth - 1])
            }
            return rsb.toString()
        }
        if (n == 4) {
            rsb.append(singleRoman[nth - 1])
            rsb.append(singleRoman[nth])
            return rsb.toString()
        }
        if (n == 5) {
            return singleRoman[nth].toString() + ""
        }
        if (n in 6..8) {
            rsb.append(singleRoman[nth])
            for (i in 0 until n - 5) {
                rsb.append(singleRoman[nth - 1])
            }
            return rsb.toString()
        }
        if (n == 9) {
            rsb.append(singleRoman[nth - 1])
            rsb.append(singleRoman[nth + 1])
            return rsb.toString()
        }
        return "ERROR!!!"
    }

    /**
     * @param num
     * - input number within range 1 ~ 3999
     * @return String Roman number
     */
    fun intToRoman(num: Int): String {
        if (num < 1 || num > 3999) {
            Timber.e( "ERROR input number is 1 ~ 3999")
            return ""
        }
        var temp = num
        val singleRoman = arrayOf("", "", "", "")
        val result = StringBuilder("")
        var digits = 0 // 1 ~ 4
        while (temp != 0) {
            temp /= 10
            digits++
        }
        temp = num
        val singleInt = IntArray(digits)
        for (i in 0 until digits) {
            singleInt[i] = temp % 10
            singleRoman[i] = singleDigitToRoman(temp % 10, i + 1)
            temp /= 10
        }
        for (i in digits - 1 downTo 0) {
            result.append(singleRoman[i])
        }
        return result.toString()
    }

    companion object {
        const val TAG = "note"
    }
}

open class CharOrderIndex(val str:String): IOrderIndex{
    override fun getIndexString(index: Int): String {
        return str
    }
}

class CircleHollowPointIndex : CharOrderIndex("○")

class SquareSolidPointIndex : CharOrderIndex("■")

class CircleSolidPointIndex : CharOrderIndex("●")

class DefaultPointIndex : CharOrderIndex("•")
